package edu.hawaii.duedates;

import java.util.Comparator;
import org.junit.Test; 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotSame;

/**
 * Some tests to check that the BorrowedItem class functions as expected.
 * 
 * @author Erin Kim and Arthur Shum
 */
public class TestBorrowedItem {
  
  private static final String dateA = "20090510";
  private static final String libraryA = "libraryA"; 
  private final BorrowedItem itemA = new BorrowedItem(libraryA, dateA, "A");
  private final BorrowedItem itemB = new BorrowedItem("libraryB", "20081005", "B");
  private final BorrowedItem itemC = new BorrowedItem("libraryC", "20080515", "C");
  private final BorrowedItem itemM = new BorrowedItem("libraryA", "20090510", "A");
  private final BorrowedItem itemN = new BorrowedItem("libraryA", "20090510", "N");

  /**
   * Tests that dueDateComparator returns a comparator for BorrowedItem objects, and that the
   * comparator's compare method works as specified in the Comparator API.
   */
  @Test
  public void testDueDateComparator() {
    Comparator<BorrowedItem> ddc = BorrowedItem.dueDateComparator;
    // Test that sgn(compare(x,y)) == -sgn(compare(y,x))
    int compAB = ddc.compare(itemA, itemB);
    int compBA = ddc.compare(itemB, itemA);
    assertEquals("Should have the same sign", Math.signum(compAB), -Math.signum(compBA), 0.01);

    // Test transitivity.
    int compBC = ddc.compare(itemB, itemC);
    int compAC = ddc.compare(itemA, itemC);
    assertTrue("Should be positive", compAB > 0);
    assertTrue("Should be positive", compBC > 0);
    assertTrue("Should be positive", compAC > 0);
    
    // Test that compare(x,y)==0 implies sgn(compare(x,z))==sgn(compare(yz)).
    int compAM = ddc.compare(itemA, itemM);
    int compMC = ddc.compare(itemM, itemC);
    assertEquals("Should be zero", 0, compAM);
    assertEquals("Should have the same sign", Math.signum(compAC), Math.signum(compMC), 0.01);
    
    // Test inequality
    int compAN = ddc.compare(itemA, itemN);
    assertNotSame("Should not be zero", 0, compAN);    
  }

  /**
   * Tests that libraryComparator returns a comparator for BorrowedItem objects, and that the
   * comparator's compare method works as specified in the Comparator API.
   */
  @Test
  public void testLibraryComparator() {
    Comparator<BorrowedItem> lnc = BorrowedItem.libraryComparator;
    
    // Test that sgn(compare(x,y)) == -sgn(compare(y,x))
    int compAB = lnc.compare(itemA, itemB);
    int compBA = lnc.compare(itemB, itemA);
    assertEquals("Should be equal", Math.signum(compAB), -Math.signum(compBA), 0.01);

    // Test transitivity.
    int compBC = lnc.compare(itemB, itemC);
    int compAC = lnc.compare(itemA, itemC);
    assertTrue("Should be negative", compAB < 0);
    assertTrue("Should be negative", compBC < 0);
    assertTrue("Should be negative", compAC < 0);

    // Test that compare(x,y)==0 implies sgn(compare(x,z))==sgn(compare(yz)).
    int compAM = lnc.compare(itemA, itemM);
    int compMC = lnc.compare(itemM, itemC);
    assertEquals("Should be zero", 0, compAM);
    assertEquals("Should be equal", Math.signum(compAC), Math.signum(compMC), 0.01);

    // Test inequality
    int compAN = lnc.compare(itemA, itemN);
    assertNotSame("Should not be zero", 0, compAN);      
  }

  /**
   * Tests that the toString method works as expected.
   */
  @Test
  public void testToString() {
    assertEquals("Expecting \"A\"", "A", itemA.toString());
  }
 
  /**
   * Tests that the correct library name is returned. 
   */
  @Test
  public void testGetLibraryName() {
    assertEquals("Expecting \"libraryA\"", libraryA, itemA.getLibraryName());
  }
  
  /**
   * Tests that the expected duedate is returned.
   */
  @Test
  public void testGetDueDate() {
    assertEquals("Expecting \"20090510\"", dateA, itemA.getYyyymmddDueDate());
  }

}
